home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i056: 2.11 News Source, Part07/09
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!rick (Rick Adams)
- Mod.sources: Volume 7, Issue 56
- Archive-name: 2.11news/Part07
-
- # To extract, sh this file
- # news 2.11 source part 7 of 9
- if test ! -d src
- then
- mkdir src
- fi
- echo x - src/funcs2.c 1>&2
- sed 's/.//' >src/funcs2.c <<'*-*-END-of-src/funcs2.c-*-*'
- -/*
- - * This software is Copyright (c) 1985 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - *
- - * funcs2 - functions used by both inews and readnews.
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)funcs2.c 1.16 10/23/86";
- -#endif /* SCCSID */
- -
- -#include "params.h"
- -
- -#ifdef SunIII
- -#ifndef INTERNET
- -#define INTERNET
- -#endif /* !INTERNET */
- -#endif /* SunIII */
- -
- -/*LINTLIBRARY*/
- -
- -/*
- - * Get user name and home directory.
- - */
- -getuser()
- -{
- - static int flag = TRUE;
- - register struct passwd *p;
- -
- - if (flag) {
- - if ((p = getpwuid(uid)) == NULL)
- - xerror("Cannot get user's name");
- - if ( username == NULL || username[0] == 0)
- - username = AllocCpy(p->pw_name);
- - userhome = AllocCpy(p->pw_dir);
- - flag = FALSE;
- - }
- - (void) strcpy(header.path, username);
- -}
- -
- -static FILE *sysfile;
- -
- -char *fldget();
- -
- -static int sfline;
- -
- -/*
- - * Open SUBFILE.
- - */
- -s_openr()
- -{
- - sysfile = xfopen(SUBFILE, "r");
- - sfline = 0;
- -}
- -
- -/*
- - * Read SUBFILE.
- - */
- -s_read(sp)
- -register struct srec *sp;
- -{
- - register char *p;
- - register int c;
- - char *e;
- - int chop_spaces = 0;
- -again:
- - p = bfr;
- - /*
- - * Read the SUBFILE (/usr/lib/news/sys) from the current
- - * position to the first unescaped newline. If a newline is
- - * escaped with a backslash (\) continue reading but throw away
- - * the backslash and newline; read the next line skipping spaces
- - * and tabs until the first non-space/tab character, then start
- - * looking for a newline again. Skipping the leading
- - * spaces/tabs after a escaped newline keeps the news groups
- - * together. If a line begins with a newline, just skip it.
- - */
- - for (e=p+LBUFLEN; p < e && (c=getc(sysfile)) != EOF; p++) {
- - *p = c;
- - if (c == '\n') {
- - sfline++;
- - if (p == bfr || p[-1] != '\\') {
- - p[1] = '\0';
- - break;
- - } else {
- - chop_spaces++;
- - p -= 2;
- - }
- - } else if (chop_spaces) {
- - if (c == '\t' || c == ' ')
- - p--;
- - else
- - chop_spaces = 0;
- - }
- - }
- - if (c == EOF) {
- - return FALSE;
- - }
- - p = bfr;
- - while (*p == ' ' || *p == '\t') /* skip leading white space */
- - p++;
- - if (*p == '\n')
- - goto again; /* skip newlines */
- - if (!nstrip(p))
- - xerror("SUBFILE (%s) line %d too long.", SUBFILE, sfline);
- - if (*p == '#')
- - goto again;
- - sp->s_xmit[0] = '\0';
- - sp->s_flags[0] = '\0';
- - sp->s_nosend = (char *)0;
- -
- - p = fldget(sp->s_name, p);
- - if (*p++ == '\0')
- - xerror("Bad SUBFILE (%s) line %d.", SUBFILE, sfline);
- -/*
- - * A sys file line reading "ME" means the name of the local system.
- - */
- - if (strcmp(sp->s_name, "ME") == 0)
- - (void) strcpy(sp->s_name, FULLSYSNAME);
- - e = index(sp->s_name, '/');
- - if (e) {
- - *e++ = '\0';
- - sp->s_nosend = e;
- - }
- - p = fldget(sp->s_nbuf, p);
- - lcase(sp->s_nbuf);
- - if (*p++ == '\0')
- - return TRUE;
- -
- - p = fldget(sp->s_flags, p);
- - if (*p++ == '\0')
- - return TRUE;
- -
- - (void) fldget(sp->s_xmit, p);
- - return TRUE;
- -}
- -
- -char *
- -fldget(q, p)
- -register char *q, *p;
- -{
- - while (*p && *p != ':') {
- - if (*p == '\\' && p[1]==':')
- - p++;
- - *q++ = *p++;
- - }
- - *q = '\0';
- - return p;
- -}
- -
- -/*
- - * Find the SUBFILE record for a system.
- - */
- -s_find(sp, system)
- -register struct srec *sp;
- -char *system;
- -{
- - s_openr();
- - while (s_read(sp))
- - if (strncmp(system, sp->s_name, SNLN) == 0) {
- - s_close();
- - return TRUE;
- - }
- - s_close();
- - return FALSE;
- -}
- -
- -/*
- - * Close sysfile.
- - */
- -s_close()
- -{
- - (void) fclose(sysfile);
- -}
- -
- -extern struct timeb Now;
- -
- -time_t
- -cgtdate(datestr)
- -char *datestr;
- -{
- - char junk[40],month[40],day[30],tod[60],year[50];
- - static time_t lasttime;
- - static char lastdatestr[BUFLEN] = "";
- -
- - if ( lastdatestr[0] && strcmp(datestr, lastdatestr) == 0)
- - return lasttime;
- - lasttime = getdate(datestr, &Now);
- - if (lasttime < 0 &&
- - sscanf(datestr, "%s %s %s %s %s", junk, month, day, tod, year) == 5) {
- - (void) sprintf(bfr, "%s %s, %s %s", month, day, year, tod);
- - lasttime = getdate(bfr, &Now);
- - }
- - strncpy(lastdatestr, datestr, BUFLEN);
- - return lasttime;
- -}
- -
- -lcase(s)
- -register char *s;
- -{
- - register char *ptr;
- -
- - for (ptr = s; *ptr; ptr++)
- - if (isupper(*ptr))
- - *ptr = tolower(*ptr);
- -}
- -
- -/*
- - * Return a compact representation of the person who posted the given
- - * message. A sender or internet name will be used, otherwise
- - * the last part of the path is used preceded by an optional ".."
- - */
- -char *
- -tailpath(hp)
- -struct hbuf *hp;
- -{
- - char *p, *r;
- - static char resultbuf[BUFLEN];
- - char pathbuf[PATHLEN];
- - char *malloc();
- -
- - /*
- - * This only happens for articles posted by old news software
- - * in non-internet format.
- - */
- - resultbuf[0] = '\0';
- - (void) strncpy(pathbuf, hp->path, PATHLEN);
- - p = index(pathbuf, ' ');
- - if (p)
- - *p = '\0'; /* Chop off trailing " (name)" */
- - r = rindex(pathbuf, '!');
- - if (r == 0) {
- - r = pathbuf;
- - } else {
- - while (r > pathbuf && *--r != '!')
- - ;
- - if (r > pathbuf) {
- - r++;
- - (void) strcpy(resultbuf, "..!");
- - }
- - }
- - (void) strcat(resultbuf, r);
- - return resultbuf;
- -}
- -
- -/*
- - * arpadate is like ctime(3) except that the time is returned in
- - * an acceptable ARPANET time format instead of ctime format.
- - */
- -char *
- -arpadate(longtime)
- -time_t *longtime;
- -{
- - register char *p, *q, *ud;
- - register int i;
- - static char b[40];
- - extern struct tm *gmtime();
- - extern char *asctime();
- -
- - /* Get current time. This will be used resolve the timezone. */
- - ud = asctime(gmtime(longtime));
- -
- - /* Crack the UNIX date line in a singularly unoriginal way. */
- - q = b;
- -
- -#ifdef notdef
- -/* until every site installs the fix to getdate.y, the day
- - of the week can cause time warps */
- - p = &ud[0]; /* Mon */
- - *q++ = *p++;
- - *q++ = *p++;
- - *q++ = *p++;
- - *q++ = ','; *q++ = ' ';
- -#endif
- -
- - p = &ud[8]; /* 16 */
- - if (*p == ' ')
- - p++;
- - else
- - *q++ = *p++;
- - *q++ = *p++; *q++ = ' ';
- -
- - p = &ud[4]; /* Sep */
- - *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ' ';
- -
- - p = &ud[22]; /* 1979 */
- - *q++ = *p++; *q++ = *p++; *q++ = ' ';
- -
- - p = &ud[11]; /* 01:03:52 */
- - for (i = 8; i > 0; i--)
- - *q++ = *p++;
- -
- - *q++ = ' ';
- - *q++ = 'G'; /* GMT */
- - *q++ = 'M';
- - *q++ = 'T';
- - *q = '\0';
- -
- - return b;
- -}
- -
- -char *
- -replyname(hptr)
- -struct hbuf *hptr;
- -{
- - register char *ptr;
- - static char tbuf[PATHLEN];
- -
- - ptr = hptr->path;
- - if (prefix(ptr, FULLSYSNAME) &&
- - index(NETCHRS, ptr[strlen(FULLSYSNAME)]))
- - ptr = index(ptr, '!') + 1;
- -#ifdef INTERNET
- - if (hptr->from[0])
- - ptr = hptr->from;
- - if (hptr->replyto[0])
- - ptr = hptr->replyto;
- -#endif
- - (void) strcpy(tbuf, ptr);
- - ptr = index(tbuf, '(');
- - if (ptr) {
- - while (ptr[-1] == ' ')
- - ptr--;
- - *ptr = 0;
- - }
- -#ifdef SunIII
- - if (ptr = rindex(tbuf, '.')) {
- - if (prefix(++ptr, "OZ")) {
- - /* some people only allow it in lower case ... */
- - strcpy(ptr, "oz");
- - return tbuf;
- - }
- - if (prefix(ptr, "UUCP") || prefix(ptr, "ARPA") ||
- - prefix(ptr, "DEC") || prefix(ptr, "CSNET")) {
- - strcat(tbuf, "@munnari.oz"); /* via sun to munnari */
- - return tbuf;
- - }
- - }
- - /*
- - * must(?) have come from a uucp site, lets look see if path passes
- - * through munnari, and if so delete the fake uucp path after that.
- - */
- - for (ptr = tbuf ;; ptr++) {
- - if (prefix(ptr, "munnari!")) {
- - strcpy(tbuf, ptr+8);
- - break;
- - }
- - ptr = index(ptr, '!');
- - if (ptr == (char *)0)
- - break;
- - }
- - /*
- - * now, just send the address we have left to munnari, and
- - * hope that something sensible will be done with it there.
- - * (This works in more cases than you'd think ...)
- - */
- - strcat(tbuf, "@munnari.oz");
- -#else /* !SunIII */
- -#ifndef INTERNET
- - /*
- - * Play games stripping off multiple berknet
- - * addresses (a!b!c:d:e => a!b!d:e) here.
- - */
- - for (ptr=tbuf; *ptr; ptr++) {
- - register char *ptr2;
- -
- - if (index(NETCHRS, *ptr) && *ptr == ':' &&
- - (ptr2=index(ptr+1, ':')))
- - (void) strcpy(ptr, ptr2);
- - }
- -#else /* INTERNET */
- - {
- - char mbuf[BUFLEN], modadd[BUFLEN];
- - FILE *mfd;
- - /* Let's find a path to the backbone */
- - sprintf(mbuf, "%s/mailpaths", LIBDIR);
- - mfd = xfopen(mbuf, "r");
- - do {
- - if (fgets(mbuf, sizeof mbuf, mfd) == NULL)
- - xerror("Can't find internet in %s/mailpaths",
- - LIBDIR);
- - } while (!prefix(mbuf, "internet"));
- - if (sscanf(mbuf, "%*s %s", modadd) != 1)
- - xerror("backbone address corrupted");
- - (void) fclose(mfd);
- - (void)strcpy(mbuf, tbuf);
- - /* If we are lucky, there is no ! or @ in the forward address */
- - if (strpbrk(modadd, "!@") == NULL) {
- - sprintf(tbuf, modadd, mbuf);
- - } else {
- - char *cp = index(mbuf, '@');
- - if (index(modadd, '@') == NULL && cp) {
- - /* we have to rearrange the address so no @ are in it */
- - char atbuf[BUFLEN];
- - *cp++ = '\0';
- - sprintf(atbuf, "%s!%s", cp, mbuf);
- - sprintf(tbuf, modadd, atbuf);
- - } else if (cp) {
- - /* some days you don't get lucky. presume the % hack */
- - *cp = '%';
- - sprintf(tbuf, modadd, mbuf);
- - }
- - }
- - }
- -#endif /* INTERNET */
- -#endif /* !SunIII */
- - return tbuf;
- -}
- -
- -#ifdef DBM
- -typedef struct {
- - char *dptr;
- - int dsize;
- -} datum;
- -#endif /* DBM */
- -
- -/*
- - * Given an article ID, find the line in the history file that mentions it.
- - * Return the text of the line, or NULL if not found. A pointer to a
- - * static area is returned.
- - */
- -char *
- -findhist(artid)
- -char *artid;
- -{
- - static char lbuf[256];
- - char oidbuf[BUFSIZ];
- - FILE *hfp;
- - register char *p;
- -#ifdef DBM
- - datum lhs, rhs;
- - datum fetch();
- - long fpos; /* We have to use an explicit variable to insure alignment */
- -#else /* !DBM */
- - char *histfile();
- -#endif /* !DBM */
- -
- - /* Try to understand old artid's as well. Assume .UUCP domain. */
- - if (artid[0] != '<') {
- - p = index(artid, '.');
- - if (p)
- - *p++ = '\0';
- - (void) sprintf(oidbuf, "<%s@%s.UUCP>", p, artid);
- - if (p)
- - *--p = '.';
- - } else
- - (void) strcpy(oidbuf, artid);
- - lcase(oidbuf);
- -#ifdef DBM
- - initdbm(ARTFILE);
- - lhs.dptr = oidbuf;
- - lhs.dsize = strlen(lhs.dptr) + 1;
- - rhs = fetch(lhs);
- - if (rhs.dptr == NULL)
- - return NULL;
- - hfp = xfopen(ARTFILE, "r");
- - /* The bcopy is NECESSARY to insure alignment on some machines */
- - bcopy(rhs.dptr, (char *)&fpos, sizeof (long));
- - fseek(hfp, fpos, 0);
- -#else /* !DBM */
- - hfp = xfopen(histfile(oidbuf), "r");
- -#endif /* !DBM */
- - while (fgets(lbuf, BUFLEN, hfp) != NULL) {
- - p = index(lbuf, '\t');
- - if (p == NULL)
- - p = index(lbuf, '\n');
- - *p = 0;
- - if (strcmp(lbuf, artid) == 0 || strcmp(lbuf, oidbuf) == 0) {
- - (void) fclose(hfp);
- - *p = '\t';
- - *(lbuf + strlen(lbuf) - 1) = 0; /* zap the \n */
- - return lbuf;
- - }
- -#ifdef DBM
- - break;
- -#endif /* DBM */
- - }
- - (void) fclose(hfp);
- - return NULL;
- -}
- -
- -/*
- - * Hunt up the article "artid", and return the newsgroup/artnum
- - * where it can be found.
- - */
- -char *
- -findfname(artid)
- -char *artid;
- -{
- - char *line, *p, *q;
- - char *findhist();
- - static char fname[BUFLEN];
- -
- - line = findhist(artid);
- - if (line) {
- - /* Look for it stored as an article, where it should be */
- - p = index(line, '\t');
- - p = index(p+1, '\t');
- - p++;
- - if (*p) {
- - q = index(p, ' ');
- - if (q)
- - *q = 0;
- - (void) strcpy(fname, p);
- - return fname;
- - }
- - }
- - return NULL;
- -}
- -
- -/*
- - * Hunt up the article "artid", fopen it for read, and return a
- - * file descriptor to it. We look everywhere we can think of.
- - */
- -FILE *
- -hfopen(artid)
- -char *artid;
- -{
- - char *p;
- - char *findhist();
- - FILE *rv = NULL;
- - char fname[BUFLEN];
- -
- - p = findfname(artid);
- - if (p) {
- - (void) strcpy(fname, dirname(p));
- - rv = fopen(fname, "r"); /* NOT xfopen! */
- - if (rv == NULL)
- - xerror("Cannot hfopen article %s", artid);
- - }
- - return rv;
- -}
- -
- -#ifdef DBM
- -/*
- -** Avoid problems of multiple dbminit calls.
- -*/
- -initdbm(name)
- -char *name;
- -{
- - static int called = 0;
- -
- - if (called != 0)
- - return;
- - called = 1;
- - (void) dbminit(name);
- -}
- -#endif
- -
- -#ifndef BSD4_2
- -/*
- - * move n bytes from a to b
- - */
- -bcopy(a, b, n)
- -register char *a, *b;
- -register n;
- -{
- - while (--n >= 0)
- - *b++ = *a++;
- -}
- -#endif
- -
- -#if !defined(BSD4_2) && !defined(BSD4_1C)
- -rename(from,to)
- -register char *from, *to;
- -{
- - (void) unlink(to);
- - if (link(from, to) < 0)
- - return -1;
- -
- - (void) unlink(from);
- - return 0;
- -}
- -#endif /* !BSD4_2 && ! BSD4_1C */
- -
- -#ifndef DBM
- -/*
- -** Generate the appropriate history subfile name
- -*/
- -char *
- -histfile(hline)
- -char *hline;
- -{
- - char *p;
- - char chr; /* least significant digit of article number */
- - static char subfile[BUFLEN];
- -
- - p = strchr(hline, '@');
- - if (p != NULL && p > hline)
- - chr = *(p - 1);
- - else
- - chr = '0';
- - if (!isdigit(chr))
- - chr = '0';
- - sprintf(subfile, "%s.d/%c", ARTFILE, chr);
- - if (access(subfile, 04) < 0)
- - return(ARTFILE);
- - return(subfile);
- -}
- -#endif /* !DBM */
- -
- -#ifdef VMS
- -/*
- - * These functions open an article with one level of indirection,
- - * to support symbolic links. xart_open exits if the open fails.
- - */
- -FILE *
- -xart_open (filename,mode)
- -char *filename,*mode;
- -{
- - FILE *fp = art_open (filename, mode);
- - extern int errno;
- - if (fp == NULL)
- - xerror("Cannot open article %s (%s): %s\n",
- - filename, mode, errmsg(errno));
- - return fp;
- -}
- -
- -FILE *
- -art_open (filename,mode)
- -char *filename,*mode;
- -{
- - char linkfile[BUFSIZ];
- - FILE *fp;
- -
- - if ((fp = fopen (filename, mode)) == NULL)
- - return NULL;
- - if (fgets (linkfile, BUFSIZ, fp) == NULL || linkfile[0] != '/') {
- - rewind (fp);
- - return fp;
- - }
- -/* Chase the symbolic link. */
- - (void) fclose (fp);
- - if ((fp = fopen (linkfile, mode)) == NULL)
- -/* Clean up dangling link, if we have the power. Ignore error if we don't. */
- - (void) unlink (filename);
- - return fp;
- -}
- -#endif /* VMS */
- *-*-END-of-src/funcs2.c-*-*
- echo x - src/getdate.y 1>&2
- sed 's/.//' >src/getdate.y <<'*-*-END-of-src/getdate.y-*-*'
- -%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
- -%{
- - /* Steven M. Bellovin (unc!smb) */
- - /* Dept. of Computer Science */
- - /* University of North Carolina at Chapel Hill */
- - /* @(#)getdate.y 2.13 9/16/86 */
- -
- -#include <sys/types.h>
- -#ifdef USG
- -struct timeb
- -{
- - time_t time;
- - unsigned short millitm;
- - short timezone;
- - short dstflag;
- -};
- -#else
- -#include <sys/timeb.h>
- -#endif
- -#include <ctype.h>
- -
- -#include "defs.h"
- -#if defined(BSD4_2) || defined (BSD4_1C)
- -#include <sys/time.h>
- -#else sane
- -#include <time.h>
- -#endif sane
- -
- -#define NULL 0
- -#define daysec (24L*60L*60L)
- - static int timeflag, zoneflag, dateflag, dayflag, relflag;
- - static time_t relsec, relmonth;
- - static int hh, mm, ss, merid, daylight;
- - static int dayord, dayreq;
- - static int month, day, year;
- - static int ourzone;
- -#define AM 1
- -#define PM 2
- -#define DAYLIGHT 1
- -#define STANDARD 2
- -#define MAYBE 3
- -%}
- -
- -%%
- -timedate: /* empty */
- - | timedate item;
- -
- -item: tspec =
- - {timeflag++;}
- - | zone =
- - {zoneflag++;}
- - | dtspec =
- - {dateflag++;}
- - | dyspec =
- - {dayflag++;}
- - | rspec =
- - {relflag++;}
- - | nspec;
- -
- -nspec: NUMBER =
- - {if (timeflag && dateflag && !relflag) year = $1;
- - else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
- -
- -tspec: NUMBER MERIDIAN =
- - {hh = $1; mm = 0; ss = 0; merid = $2;}
- - | NUMBER ':' NUMBER =
- - {hh = $1; mm = $3; merid = 24;}
- - | NUMBER ':' NUMBER MERIDIAN =
- - {hh = $1; mm = $3; merid = $4;}
- - | NUMBER ':' NUMBER NUMBER =
- - {hh = $1; mm = $3; merid = 24;
- - daylight = STANDARD; ourzone = $4%100 + 60*$4/100;}
- - | NUMBER ':' NUMBER ':' NUMBER =
- - {hh = $1; mm = $3; ss = $5; merid = 24;}
- - | NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
- - {hh = $1; mm = $3; ss = $5; merid = $6;}
- - | NUMBER ':' NUMBER ':' NUMBER NUMBER =
- - {hh = $1; mm = $3; ss = $5; merid = 24;
- - daylight = STANDARD; ourzone = $6%100 + 60*$6/100;};
- -
- -zone: ZONE =
- - {ourzone = $1; daylight = STANDARD;}
- - | DAYZONE =
- - {ourzone = $1; daylight = DAYLIGHT;};
- -
- -dyspec: DAY =
- - {dayord = 1; dayreq = $1;}
- - | DAY ',' =
- - {dayord = 1; dayreq = $1;}
- - | NUMBER DAY =
- - {dayord = $1; dayreq = $2;};
- -
- -dtspec: NUMBER '/' NUMBER =
- - {month = $1; day = $3;}
- - | NUMBER '/' NUMBER '/' NUMBER =
- - {month = $1; day = $3; year = $5;}
- - | MONTH NUMBER =
- - {month = $1; day = $2;}
- - | MONTH NUMBER ',' NUMBER =
- - {month = $1; day = $2; year = $4;}
- - | NUMBER MONTH =
- - {month = $2; day = $1;}
- - | NUMBER MONTH NUMBER =
- - {month = $2; day = $1; year = $3;};
- -
- -
- -rspec: NUMBER UNIT =
- - {relsec += 60L * $1 * $2;}
- - | NUMBER MUNIT =
- - {relmonth += $1 * $2;}
- - | NUMBER SUNIT =
- - {relsec += $1;}
- - | UNIT =
- - {relsec += 60L * $1;}
- - | MUNIT =
- - {relmonth += $1;}
- - | SUNIT =
- - {relsec++;}
- - | rspec AGO =
- - {relsec = -relsec; relmonth = -relmonth;};
- -%%
- -
- -static int mdays[12] =
- - {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- -#define epoch 1970
- -
- -extern struct tm *localtime();
- -time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
- -int mm, dd, yy, h, m, s, mer, zone, dayflag;
- -{
- - time_t tod, jdate;
- - register int i;
- - time_t timeconv();
- -
- - if (yy < 0) yy = -yy;
- - if (yy < 100) yy += 1900;
- - mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
- - if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
- - dd < 1 || dd > mdays[--mm]) return (-1);
- - jdate = dd-1;
- - for (i=0; i<mm; i++) jdate += mdays[i];
- - for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
- - jdate *= daysec;
- - jdate += zone * 60L;
- - if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
- - jdate += tod;
- - if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
- - jdate += -1*60*60;
- - return (jdate);
- -}
- -
- -time_t dayconv(ord, day, now) int ord, day; time_t now;
- -{
- - register struct tm *loctime;
- - time_t tod;
- - time_t daylcorr();
- -
- - tod = now;
- - loctime = localtime(&tod);
- - tod += daysec * ((day - loctime->tm_wday + 7) % 7);
- - tod += 7*daysec*(ord<=0?ord:ord-1);
- - return daylcorr(tod, now);
- -}
- -
- -time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
- -{
- - if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
- - switch (mer) {
- - case AM: if (hh < 1 || hh > 12) return(-1);
- - return (60L * ((hh%12)*60L + mm)+ss);
- - case PM: if (hh < 1 || hh > 12) return(-1);
- - return (60L * ((hh%12 +12)*60L + mm)+ss);
- - case 24: if (hh < 0 || hh > 23) return (-1);
- - return (60L * (hh*60L + mm)+ss);
- - default: return (-1);
- - }
- -}
- -time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
- -{
- - struct tm *ltime;
- - time_t dateconv();
- - time_t daylcorr();
- - int mm, yy;
- -
- - if (relmonth == 0) return 0;
- - ltime = localtime(&sdate);
- - mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
- - yy = mm/12;
- - mm = mm%12 + 1;
- - return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
- - ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
- -}
- -
- -time_t daylcorr(future, now) time_t future, now;
- -{
- - int fdayl, nowdayl;
- -
- - nowdayl = (localtime(&now)->tm_hour+1) % 24;
- - fdayl = (localtime(&future)->tm_hour+1) % 24;
- - return (future-now) + 60L*60L*(nowdayl-fdayl);
- -}
- -
- -static char *lptr;
- -
- -yylex()
- -{
- - extern int yylval;
- - int sign;
- - register char c;
- - register char *p;
- - char idbuf[20];
- - int pcnt;
- -
- - for (;;) {
- - while (isspace(*lptr)) lptr++;
- -
- - if (isdigit(c = *lptr) || c == '-' || c == '+') {
- - if (c== '-' || c == '+') {
- - if (c=='-') sign = -1;
- - else sign = 1;
- - if (!isdigit(*++lptr)) {
- - /* yylval = sign; return (NUMBER); */
- - return yylex(); /* skip the '-' sign */
- - }
- - } else sign = 1;
- - yylval = 0;
- - while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
- - yylval *= sign;
- - lptr--;
- - return (NUMBER);
- -
- - } else if (isalpha(c)) {
- - p = idbuf;
- - while (isalpha(c = *lptr++) || c=='.')
- - *p++ = c;
- - *p = '\0';
- - lptr--;
- - return (lookup(idbuf));
- - }
- -
- - else if (c == '(') {
- - pcnt = 0;
- - do {
- - c = *lptr++;
- - if (c == '\0') return(c);
- - else if (c == '(') pcnt++;
- - else if (c == ')') pcnt--;
- - } while (pcnt > 0);
- - }
- -
- - else return (*lptr++);
- - }
- -}
- -
- -struct table {
- - char *name;
- - int type, value;
- -};
- -
- -struct table mdtab[] = {
- - {"January", MONTH, 1},
- - {"February", MONTH, 2},
- - {"March", MONTH, 3},
- - {"April", MONTH, 4},
- - {"May", MONTH, 5},
- - {"June", MONTH, 6},
- - {"July", MONTH, 7},
- - {"August", MONTH, 8},
- - {"September", MONTH, 9},
- - {"Sept", MONTH, 9},
- - {"October", MONTH, 10},
- - {"November", MONTH, 11},
- - {"December", MONTH, 12},
- -
- - {"Sunday", DAY, 0},
- - {"Monday", DAY, 1},
- - {"Tuesday", DAY, 2},
- - {"Tues", DAY, 2},
- - {"Wednesday", DAY, 3},
- - {"Wednes", DAY, 3},
- - {"Thursday", DAY, 4},
- - {"Thur", DAY, 4},
- - {"Thurs", DAY, 4},
- - {"Friday", DAY, 5},
- - {"Saturday", DAY, 6},
- - {0, 0, 0}};
- -
- -#define HRS *60
- -#define HALFHR 30
- -struct table mztab[] = {
- - {"a.m.", MERIDIAN, AM},
- - {"am", MERIDIAN, AM},
- - {"p.m.", MERIDIAN, PM},
- - {"pm", MERIDIAN, PM},
- - {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
- - {"n.s.t.", ZONE, 3 HRS + HALFHR},
- - {"ast", ZONE, 4 HRS}, /* Atlantic */
- - {"a.s.t.", ZONE, 4 HRS},
- - {"adt", DAYZONE, 4 HRS},
- - {"a.d.t.", DAYZONE, 4 HRS},
- - {"est", ZONE, 5 HRS}, /* Eastern */
- - {"e.s.t.", ZONE, 5 HRS},
- - {"edt", DAYZONE, 5 HRS},
- - {"e.d.t.", DAYZONE, 5 HRS},
- - {"cst", ZONE, 6 HRS}, /* Central */
- - {"c.s.t.", ZONE, 6 HRS},
- - {"cdt", DAYZONE, 6 HRS},
- - {"c.d.t.", DAYZONE, 6 HRS},
- - {"mst", ZONE, 7 HRS}, /* Mountain */
- - {"m.s.t.", ZONE, 7 HRS},
- - {"mdt", DAYZONE, 7 HRS},
- - {"m.d.t.", DAYZONE, 7 HRS},
- - {"pst", ZONE, 8 HRS}, /* Pacific */
- - {"p.s.t.", ZONE, 8 HRS},
- - {"pdt", DAYZONE, 8 HRS},
- - {"p.d.t.", DAYZONE, 8 HRS},
- - {"yst", ZONE, 9 HRS}, /* Yukon */
- - {"y.s.t.", ZONE, 9 HRS},
- - {"ydt", DAYZONE, 9 HRS},
- - {"y.d.t.", DAYZONE, 9 HRS},
- - {"hst", ZONE, 10 HRS}, /* Hawaii */
- - {"h.s.t.", ZONE, 10 HRS},
- - {"hdt", DAYZONE, 10 HRS},
- - {"h.d.t.", DAYZONE, 10 HRS},
- -
- - {"gmt", ZONE, 0 HRS},
- - {"g.m.t.", ZONE, 0 HRS},
- - {"bst", DAYZONE, 0 HRS}, /* British Summer Time */
- - {"b.s.t.", DAYZONE, 0 HRS},
- - {"eet", ZONE, 0 HRS}, /* European Eastern Time */
- - {"e.e.t.", ZONE, 0 HRS},
- - {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
- - {"e.e.s.t.", DAYZONE, 0 HRS},
- - {"met", ZONE, -1 HRS}, /* Middle European Time */
- - {"m.e.t.", ZONE, -1 HRS},
- - {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
- - {"m.e.s.t.", DAYZONE, -1 HRS},
- - {"wet", ZONE, -2 HRS }, /* Western European Time */
- - {"w.e.t.", ZONE, -2 HRS },
- - {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
- - {"w.e.s.t.", DAYZONE, -2 HRS},
- -
- - {"jst", ZONE, -9 HRS}, /* Japan Standard Time */
- - {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
- - /* No daylight savings time */
- -
- - {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
- - {"a.e.s.t.", ZONE, -10 HRS},
- - {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
- - {"a.e.s.s.t.", DAYZONE, -10 HRS},
- - {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
- - {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
- - {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
- - {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
- - {"awst", ZONE, -8 HRS}, /* Australian Western Time */
- - {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
- - {0, 0, 0}};
- -
- -struct table unittb[] = {
- - {"year", MUNIT, 12},
- - {"month", MUNIT, 1},
- - {"fortnight", UNIT, 14*24*60},
- - {"week", UNIT, 7*24*60},
- - {"day", UNIT, 1*24*60},
- - {"hour", UNIT, 60},
- - {"minute", UNIT, 1},
- - {"min", UNIT, 1},
- - {"second", SUNIT, 1},
- - {"sec", SUNIT, 1},
- - {0, 0, 0}};
- -
- -struct table othertb[] = {
- - {"tomorrow", UNIT, 1*24*60},
- - {"yesterday", UNIT, -1*24*60},
- - {"today", UNIT, 0},
- - {"now", UNIT, 0},
- - {"last", NUMBER, -1},
- - {"this", UNIT, 0},
- - {"next", NUMBER, 2},
- - {"first", NUMBER, 1},
- - /* {"second", NUMBER, 2}, */
- - {"third", NUMBER, 3},
- - {"fourth", NUMBER, 4},
- - {"fifth", NUMBER, 5},
- - {"sixth", NUMBER, 6},
- - {"seventh", NUMBER, 7},
- - {"eigth", NUMBER, 8},
- - {"ninth", NUMBER, 9},
- - {"tenth", NUMBER, 10},
- - {"eleventh", NUMBER, 11},
- - {"twelfth", NUMBER, 12},
- - {"ago", AGO, 1},
- - {0, 0, 0}};
- -
- -struct table milzone[] = {
- - {"a", ZONE, 1 HRS},
- - {"b", ZONE, 2 HRS},
- - {"c", ZONE, 3 HRS},
- - {"d", ZONE, 4 HRS},
- - {"e", ZONE, 5 HRS},
- - {"f", ZONE, 6 HRS},
- - {"g", ZONE, 7 HRS},
- - {"h", ZONE, 8 HRS},
- - {"i", ZONE, 9 HRS},
- - {"k", ZONE, 10 HRS},
- - {"l", ZONE, 11 HRS},
- - {"m", ZONE, 12 HRS},
- - {"n", ZONE, -1 HRS},
- - {"o", ZONE, -2 HRS},
- - {"p", ZONE, -3 HRS},
- - {"q", ZONE, -4 HRS},
- - {"r", ZONE, -5 HRS},
- - {"s", ZONE, -6 HRS},
- - {"t", ZONE, -7 HRS},
- - {"u", ZONE, -8 HRS},
- - {"v", ZONE, -9 HRS},
- - {"w", ZONE, -10 HRS},
- - {"x", ZONE, -11 HRS},
- - {"y", ZONE, -12 HRS},
- - {"z", ZONE, 0 HRS},
- - {0, 0, 0}};
- -
- -lookup(id) char *id;
- -{
- -#define gotit (yylval=i->value, i->type)
- -#define getid for(j=idvar, k=id; *j++ = *k++; )
- -
- - char idvar[20];
- - register char *j, *k;
- - register struct table *i;
- - int abbrev;
- -
- - getid;
- - if (strlen(idvar) == 3) abbrev = 1;
- - else if (strlen(idvar) == 4 && idvar[3] == '.') {
- - abbrev = 1;
- - idvar[3] = '\0';
- - }
- - else abbrev = 0;
- -
- - if (islower(*idvar)) *idvar = toupper(*idvar);
- -
- - for (i = mdtab; i->name; i++) {
- - k = idvar;
- - for (j = i->name; *j++ == *k++;) {
- - if (abbrev && j==i->name+3) return gotit;
- - if (j[-1] == 0) return gotit;
- - }
- - }
- -
- - getid;
- - for (i = mztab; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- -
- - for (j = idvar; *j; j++)
- - if (isupper(*j)) *j = tolower(*j);
- - for (i=mztab; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- -
- - getid;
- - for (i=unittb; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- -
- - if (idvar[strlen(idvar)-1] == 's')
- - idvar[strlen(idvar)-1] = '\0';
- - for (i=unittb; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- -
- - getid;
- - for (i = othertb; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- -
- - getid;
- - if (strlen(idvar) == 1 && isalpha(*idvar)) {
- - if (isupper(*idvar)) *idvar = tolower(*idvar);
- - for (i = milzone; i->name; i++)
- - if (strcmp(i->name, idvar) == 0) return gotit;
- - }
- -
- - return(ID);
- -}
- -
- -time_t getdate(p, now) char *p; struct timeb *now;
- -{
- -#define mcheck(f) if (f>1) err++
- - time_t monthadd();
- - int err;
- - struct tm *lt;
- - struct timeb ftz;
- -
- - time_t sdate, tod;
- -
- - lptr = p;
- - if (now == ((struct timeb *) NULL)) {
- - now = &ftz;
- - ftime(&ftz);
- - }
- - lt = localtime(&now->time);
- - year = lt->tm_year;
- - month = lt->tm_mon+1;
- - day = lt->tm_mday;
- - relsec = 0; relmonth = 0;
- - timeflag=zoneflag=dateflag=dayflag=relflag=0;
- - ourzone = now->timezone;
- - daylight = MAYBE;
- - hh = mm = ss = 0;
- - merid = 24;
- -
- - if (err = yyparse()) return (-1);
- -
- - mcheck(timeflag);
- - mcheck(zoneflag);
- - mcheck(dateflag);
- - mcheck(dayflag);
- -
- - if (err) return (-1);
- - if (dateflag || timeflag || dayflag) {
- - sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
- - if (sdate < 0) return -1;
- - }
- - else {
- - sdate = now->time;
- - if (relflag == 0)
- - sdate -= (lt->tm_sec + lt->tm_min*60 +
- - lt->tm_hour*(60L*60L));
- - }
- -
- - sdate += relsec;
- - sdate += monthadd(sdate, relmonth);
- -
- - if (dayflag && !dateflag) {
- - tod = dayconv(dayord, dayreq, sdate);
- - sdate += tod;
- - }
- -
- - return sdate;
- -}
- -
- -yyerror(s) char *s;
- -{}
- *-*-END-of-src/getdate.y-*-*
- echo x - src/funcs.c 1>&2
- sed 's/.//' >src/funcs.c <<'*-*-END-of-src/funcs.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * funcs - functions used by many programs
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)funcs.c 2.33 10/23/86";
- -#endif /* SCCSID */
- -
- -/*LINTLIBRARY*/
- -
- -#include "params.h"
- -#include <errno.h>
- -#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
- -#include <fcntl.h>
- -#endif /* !v7 */
- -
- -extern char *Progname;
- -
- -/*
- - * News group matching.
- - *
- - * nglist is a list of newsgroups.
- - * sublist is a list of subscriptions.
- - * sublist may have "meta newsgroups" in it.
- - * All fields are NGDELIM separated,
- - * and there is an NGDELIM at the end of each argument.
- - *
- - * Currently implemented glitches:
- - * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
- - * If subscription X matches Y, it also matches Y.anything.
- - */
- -ngmatch(nglist, sublist)
- -register char *nglist, *sublist;
- -{
- - register char *n, *s;
- - register int rc;
- -
- - rc = FALSE;
- - for (n = nglist; *n != '\0' && rc == FALSE;) {
- - for (s = sublist; *s != '\0';) {
- - if (*s != NEGCHAR)
- - rc = rc || ptrncmp(s, n);
- - else
- - rc = rc && !ptrncmp(s+1, n);
- - while (*s++ != NGDELIM && *s != '\0')
- - ;
- - }
- - while (*n++ != NGDELIM && *n != '\0')
- - ;
- - }
- - return rc;
- -}
- -
- -/*
- - * Compare two newsgroups for equality.
- - * The first one may be a "meta" newsgroup.
- - */
- -ptrncmp(ng1, ng2)
- -register char *ng1, *ng2;
- -{
- - while (*ng1 != NGDELIM && *ng1 != '\0') {
- - if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
- - ng1 += 3;
- - while (*ng2 != NGDELIM && *ng2 != '.' && *ng2 != '\0')
- - if (ptrncmp(ng1, ng2++))
- - return(TRUE);
- - return ptrncmp(ng1, ng2);
- - } else if (*ng1++ != *ng2++)
- - return FALSE;
- - }
- - return *ng2 == '.' || *ng2 == NGDELIM || *ng2 == '\0';
- -}
- -
- -/*
- - * Exec the shell.
- - * This version resets uid, gid, and umask.
- - * Called with fsubr(ushell, s, NULL)
- - */
- -/* ARGSUSED */
- -ushell(s, dummy)
- -char *s, *dummy;
- -{
- - (void) umask(savmask);
- - (void) setgid(gid);
- - (void) setuid(uid);
- - xshell(s);
- -}
- -
- -/*
- - * Exec the shell.
- - */
- -
- -#ifdef lint
- -char **environ;
- -#else /* !lint */
- -extern char **environ;
- -#endif /* !lint */
- -
- -xshell(s)
- -char *s;
- -{
- - char *env[100], **envp;
- - char a[BUFLEN + 2];
- - extern char filename[];
- - /* set $A */
- - (void) sprintf(a, "A=%s", filename);
- - env[0] = a;
- - for (envp = env + 1 ; *environ != NULL && envp < env + 98 ; environ++)
- - if ((*environ)[0] != 'A' || (*environ)[1] != '=')
- - *envp++ = *environ;
- - *envp = NULL;
- -
- - execle(SHELL, SHELL, "-c", s, (char *)0, env);
- - xerror("No shell!");
- -}
- -
- -/*
- - * Fork and call a subroutine with two args.
- - * Return pid without waiting.
- - */
- -fsubr(f, s1, s2)
- -int (*f)();
- -char *s1, *s2;
- -{
- - register int pid;
- -
- - /* this may NOT be a vfork */
- - while ((pid = fork()) == -1)
- - sleep((unsigned)1);
- - if (pid == 0) {
- - (*f)(s1, s2);
- - exit(0);
- - }
- - return pid;
- -}
- -
- -/*
- - * Wait on a child process.
- - */
- -fwait(pid)
- -register int pid;
- -{
- - register int w;
- - int status;
- - int (*onhup)(), (*onint)();
- -
- - onint = signal(SIGINT, SIG_IGN);
- - onhup = signal(SIGHUP, SIG_IGN);
- - while ((w = wait(&status)) != pid && w != -1)
- - ;
- - if (w == -1)
- - status = -1;
- - (void) signal(SIGINT, onint);
- - (void) signal(SIGHUP, onhup);
- - return status;
- -}
- -
- -/*
- - * Strip trailing newlines, blanks, and tabs from 's'.
- - * Return TRUE if newline was found, else FALSE.
- - */
- -nstrip(s)
- -register char *s;
- -{
- - register char *p;
- - register int rc;
- -
- - rc = FALSE;
- - p = s;
- - while (*p)
- - if (*p++ == '\n')
- - rc = TRUE;
- - while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
- - *++p = '\0';
- - return rc;
- -}
- -
- -/*
- - * Local open routine.
- - */
- -FILE *
- -xfopen(name, fmode)
- -register char *name, *fmode;
- -{
- - register FILE *fp;
- - char *fname;
- - extern int errno;
- -
- - if ((fp = fopen(name, fmode)) == NULL) {
- -#ifdef IHCC
- - /*
- - * IHCC users only see the "filename" that was in trouble,
- - * not the whole path. (for security!)
- - */
- - fname = rindex(name, '/') + 1;
- -#else
- - fname = name;
- -#endif
- - xerror("Cannot open %s (%s): %s", fname, fmode, errmsg(errno));
- - }
- - /* kludge for setuid not being honored for root */
- - if ((uid == 0) && (duid != 0) && ((*fmode == 'a') || (*fmode == 'w')))
- - (void) chown(name, duid, dgid);
- - return fp;
- -}
- -
- -char *
- -errmsg(code)
- -int code;
- -{
- - extern int sys_nerr;
- - extern char *sys_errlist[];
- - static char ebuf[6+5+1];
- -
- - if (code > sys_nerr) {
- - (void) sprintf(ebuf, "Error %d", code);
- - return ebuf;
- - } else
- - return sys_errlist[code];
- -}
- -
- -prefix(full, pref)
- -register char *full, *pref;
- -{
- - register char fc, pc;
- -
- - while ((pc = *pref++) != '\0') {
- - fc = *full++;
- - if (isupper(fc))
- - fc = tolower(fc);
- - if (isupper(pc))
- - pc = tolower(pc);
- - if (fc != pc)
- - return FALSE;
- - }
- - return TRUE;
- -}
- -
- -char *
- -dirname(ngname)
- -char *ngname;
- -{
- - static char rbuf[BUFLEN];
- - register char *p;
- -
- - (void) sprintf(rbuf, "%s/%s", SPOOL, ngname);
- -
- - for (p=rbuf+strlen(SPOOL); *p; p++)
- - if (*p == '.')
- - *p = '/';
- - return rbuf;
- -}
- -
- -/*
- - * Return TRUE iff ngname is a valid newsgroup name
- - */
- -validng(ngname)
- -char *ngname;
- -{
- - register FILE *fp;
- - register char *p, *q;
- - char abuf[BUFLEN];
- -
- - fp = xfopen(ACTIVE, "r");
- - while(fgets(abuf, BUFLEN, fp) != NULL) {
- - p = abuf;
- - q = ngname;
- - while (*p++ == *q++)
- - ;
- - if (*--q == '\0' && *--p == ' ') {
- - (void) fclose(fp);
- - return TRUE;
- - }
- - }
- - (void) fclose(fp);
- - return FALSE;
- -}
- -
- -/* VARARGS1 */
- -xerror(message, arg1, arg2, arg3)
- -char *message;
- -long arg1, arg2, arg3;
- -{
- - char buffer[LBUFLEN];
- -
- - fflush(stdout);
- - (void) sprintf(buffer, message, arg1, arg2, arg3);
- - logerr(buffer);
- - xxit(1);
- -}
- -
- -/* VARARGS1 */
- -log(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- -char *fmt;
- -long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- -{
- - _dolog(0, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- -}
- -
- -/* VARARGS1 */
- -logerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- -char *fmt;
- -long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- -{
- - _dolog(1, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- -}
- -
- -char *lfsuffix[] = {
- - "log",
- - "errlog",
- - 0
- -};
- -
- -/*
- - * Log the given message, with printf strings and parameters allowed,
- - * on the log file, if it can be written. The date and an attempt at
- - * figuring out the remote system name are also logged.
- - */
- -/* VARARGS1 */
- -_dolog(which, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- -char *fmt;
- -long a1, a2, a3, a4, a5, a6, a7, a8, a9;
- -{
- - FILE *logfile;
- - register char *p, *logtime;
- - int i;
- - char logfname[BUFLEN]; /* the log file */
- - char rmtsys[BUFLEN];
- - char msg[LBUFLEN];
- - time_t t;
- -
- - (void) strcpy(rmtsys, header.path);
- - p = index(rmtsys, '!');
- - if (p == NULL)
- - p = index(rmtsys, ':');
- - if (p)
- - *p = 0;
- - else {
- - p = rindex(rmtsys, '@');
- - if (p)
- - (void) strcpy(rmtsys, p+1);
- - else
- - (void) strcpy(rmtsys, "local");
- - }
- -
- - (void) time(&t);
- - logtime = ctime(&t);
- - logtime[16] = 0;
- - logtime += 4;
- -
- -
- - (void) sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- -
- - if (which)
- - fprintf(stderr,"%s: %s\n", Progname, msg);
- -
- - for (i=0; i<=which;i++) {
- - (void) sprintf(logfname, "%s/%s", LIB, lfsuffix[i]);
- -
- - if (access(logfname, 0) == 0 && (logfile = fopen(logfname, "a")) != NULL) {
- -#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
- - int flags;
- - flags = fcntl(fileno(logfile), F_GETFL, 0);
- - (void) fcntl(fileno(logfile), F_SETFL, flags|O_APPEND);
- -#else /* v7 */
- - (void) lseek(fileno(logfile), 0L, 2);
- -#endif /* v7 */
- - if (i)
- - fprintf(logfile, "%s\t%s\t%s: %s\n", logtime,
- - header.ident[0] ? header.ident : username, Progname, msg);
- - else
- - fprintf(logfile, "%s\t%s\t%s\n", logtime,
- - rmtsys, msg);
- - (void) fclose(logfile);
- - }
- - }
- -}
- -#ifdef VMS
- -
- -/*
- - * vmslink allows simulation of file linking under VMS.
- - */
- -vmslink(infile,outfile)
- -char *infile, *outfile;
- -{
- - FILE *fp;
- -
- - if (access(outfile,0) == 0) {
- - errno = EEXIST;
- - return -1;
- - }
- -
- - fp = fopen(outfile, "w");
- - if (fp == NULL) {
- - errno = EACCES;
- - return -1;
- - }
- -
- - (void) fprintf(fp, "%s", infile);
- - (void) fclose(fp);
- -
- - return 0;
- -}
- -
- -/*
- - * vmsdelete deletes all revisions of a file. It attempts to
- - * appear as unlink(2) under conventional Unix in other respects.
- - */
- -vmsdelete(file)
- -char *file;
- -{
- - int i;
- -
- - i = unlink(file);
- - if (i != 0)
- - return i;
- -
- - i = errno;
- - while (unlink(file) == 0)
- - ;
- - errno = i;
- -
- - return 0;
- -}
- -
- -/*
- - * Convert a Unix file to a VMS fixed record format file by
- - * executing the 'unixtovms' command.
- - */
- -unixtovms(file)
- -char *file;
- -{
- - char buf[BUFLEN];
- - sprintf(buf, "exec /etc/unixtovms %s", file);
- - return system(buf);
- -}
- -
- -/*
- - * Convert a VMS fixed record format file to a Unix file by
- - * executing the 'vmstounix' command.
- - */
- -vmstounix(file)
- -char *file;
- -{
- - char buf[BUFLEN];
- - sprintf(buf,"exec /etc/vmstounix %s", file);
- - return system(buf);
- -}
- -#endif /* VMS */
- -
- -#if !defined(BSD4_2) && !defined(BSD4_1C)
- -/*
- - * make a directory. Also make sure that the directory is owned
- - * by the right userid
- - */
- -mkdir(path, perm)
- -char *path;
- -int perm;
- -{
- - int pid, status;
- -
- - if (pid=vfork()) {
- - status = fwait(pid);
- -#if defined(USG) && !defined(CHEAP)
- - if (pid=vfork())
- - (void) fwait(pid);
- - else {
- - setgid(gid);
- - setuid(uid);
- - if (chown(path, duid, dgid) == 0)
- - (void) chmod(path, perm&(~N_UMASK));
- - _exit(0);
- - }
- -#endif /* USG && !CHEAP */
- - } else {
- - (void) setgid(dgid);
- - if (setuid(duid) < 0)
- - (void) umask(0);
- - else
- - (void) umask(perm&N_UMASK);
- - (void) execlp("mkdir", "mkdir", path, (char *)NULL);
- - perror(path);
- - _exit(1);
- - }
- - return status;
- -}
- -#endif /* !BSD4_2 && ! BSD4_1C */
- -#ifndef USG
- -char *
- -strpbrk(str, chars)
- -register char *str, *chars;
- -{
- - register char *cp;
- -
- - do {
- - cp = chars - 1;
- - while (*++cp) {
- - if (*str == *cp)
- - return str;
- - }
- - } while (*str++);
- - return NULL;
- -}
- -#endif /* !USG */
- -
- -#ifdef FASCIST
- -/*
- - * This routine checks to see if the posting user is allowed to
- - * post to the given newsgroup. If the username is not in the file
- - * $LIBDIR/authorized then the default in the symbol FASCIST is used.
- - *
- - * Format of the call:
- - * fascist(user, newgroups)
- - *
- - * Returns:
- - * FALSE, if authorized
- - * TRUE, if not
- - *
- - * Format of the file "authorized" is:
- - * user:allowed groups
- - *
- - * Example:
- - * root:net.all,mod.all
- - * naughty_person:junk,net.politics
- - * operator:!net.all,general,test,mod.unix
- - *
- - * An open environment could have FASCIST set to "all"
- - * and then individual entries could be made in the authorized file
- - * to prevent certain individuals from posting to such a wide
- - * area.
- - *
- - * Note that a distribution of "all" does NOT mean to allow postings
- - * only to local groups -- "all" includes "all.all".
- - * Use "all,!all.all" to get this behavior
- - *
- - * Eugene Spafford spaf@gatech May 22, 1985
- - */
- -
- -fascist(user, newsgroups)
- -register char *user, *newsgroups;
- -{
- - FILE *facfd;
- - char facuser[BUFLEN], facgroups[BUFLEN], factemp[BUFLEN];
- - register char *facptr;
- -
- - /* First, open the necessary file...$LIBDIR/authorized and see if there
- - * is an entry for this user
- - */
- -
- - (void) strncpy(facgroups, FASCIST, BUFLEN);
- - sprintf(factemp, "%s/%s", LIBDIR, "authorized");
- - facfd = fopen(factemp, "r");
- -
- - if (facfd != NULL) { /* If no such file, we go with the global default */
- - while (fscanf(facfd, "%[^:]:%s\n", facuser, factemp) != EOF)
- - if (strncmp(facuser, user, BUFLEN) == 0) {
- - (void) strcat(facgroups, ",");
- - (void) strcat(facgroups, factemp);
- - break;
- - }
- - fclose (facfd);
- - }
- -#ifdef DEBUG
- - fprintf(stderr, "facgroups = %s\n", facgroups);
- - fprintf(stderr, "newsgroups = %s\n", newsgroups);
- -#endif DEBUG
- -
- - /* We step through the newsgroups being posted to and check each against
- - * the restriction list. *ALL* posted groups must match the restriction
- - * list or we don't allow the posting.
- - */
- -
- - while (*newsgroups != '\0') {
- - facptr = factemp;
- - while (*newsgroups != '\0' && *newsgroups != NGDELIM)
- - *facptr++ = *newsgroups++;
- - *facptr = '\0';
- - if (*newsgroups == NGDELIM)
- - newsgroups++;
- -
- -#ifdef DEBUG
- - fprintf(stderr, "Checking newsgroup '%s'\n", factemp);
- -#endif
- -
- - if (ngmatch(factemp, facgroups) == FALSE)
- - return TRUE;
- - }
- -
- - /* must be okay -- return */
- -#ifdef DEBUG
- - fprintf (stderr, "Newsgroups approved for this poster.\n");
- -#endif DEBUG
- - return FALSE;
- -}
- -#endif FASCIST
- *-*-END-of-src/funcs.c-*-*
- echo x - src/checknews.c 1>&2
- sed 's/.//' >src/checknews.c <<'*-*-END-of-src/checknews.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * checknews - news checking program
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)checknews.c 2.25 5/27/86";
- -#endif /* SCCSID */
- -
- -char *Progname = "checknews"; /* used by xerror */
- -
- -#include "params.h"
- -
- -char bfr[LBUFLEN]; /* general-use scratch area */
- -char optbuf[BUFLEN]; /* NEWSOPTS buffer */
- -int line = -1, y, e, n, q;
- -int verbose; /* For debugging. */
- -int nflag; /* for spec. newsgroup */
- -char narggrp[BUFLEN]; /* spec newsgroup */
- -FILE *rcfp, *actfp;
- -char newsrc[BUFLEN],*rcline[LINES],rcbuf[LBUFLEN],*argvrc[LINES];
- -struct hbuf header;
- -char coptbuf[BUFLEN],datebuf[BUFLEN];
- -int mode = 1;
- -#ifndef SHELL
- -char *SHELL;
- -#endif
- -
- -main(argc, argv)
- -int argc;
- -register char **argv;
- -{
- - register char *ptr; /* pointer to rest of buffer */
- - char *user, *home;
- - struct passwd *pw;
- - struct group *gp;
- - int sflag = 0, optflag = FALSE, space = FALSE;
- - int i;
- -
- - y = 0;
- - n = 0;
- - e = 0;
- - q = 0;
- - nflag = 0;
- - pathinit();
- - if (--argc > 0) {
- - for (argv++; **argv; ++*argv) {
- - switch(**argv) {
- - case 'y':
- - y++;
- - break;
- - case 'q':
- - q++;
- - break;
- - case 'v':
- - verbose++;
- - break;
- - case 'n':
- - n++;
- - break;
- - case 'N':
- - nflag++;
- - strcpy(narggrp,argv[1]);
- - strcat(narggrp,",");
- - break;
- - case 'e':
- - case 'f':
- - e++;
- - break;
- - }
- - }
- - }
- - if (!n && !e && !y && !q)
- - y++;
- - if (nflag)
- - argv++;
- -
- -#ifndef V6
- - if ((user = getenv("USER")) == NULL)
- - user = getenv("LOGNAME");
- - if ((home = getenv("HOME")) == NULL)
- - home = getenv("LOGDIR");
- - if (user == NULL || home == NULL)
- - getuser();
- - else {
- - username = AllocCpy(user);
- - userhome = AllocCpy(home);
- - }
- - if (ptr = getenv("NEWSOPTS"))
- - strcpy(rcbuf, ptr);
- - else
- - *rcbuf = '\0';
- - if (*rcbuf) {
- - strcat(rcbuf, " \1");
- - ptr = rcbuf;
- - while (*++ptr)
- - if (isspace(*ptr))
- - *ptr = '\0';
- - for (ptr = rcbuf;; ptr++) {
- - if (!*ptr)
- - continue;
- - if (*ptr == '\1')
- - break;
- - if (++line > LINES)
- - xerror("Too many options.");
- - if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
- - xerror("Not enough memory.");
- - argvrc[line] = rcline[line];
- - strcpy(rcline[line], ptr);
- - while (*ptr)
- - ptr++;
- - }
- - }
- -#else
- - getuser();
- -#endif
- - ptr = getenv("NEWSRC");
- - if (ptr == NULL)
- - sprintf(newsrc, "%s/%s", userhome, NEWSRC);
- - else
- - strcpy(newsrc, ptr);
- - if ((rcfp = fopen(newsrc, "r")) != NULL) {
- - while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
- - if (!(space = isspace(*rcbuf)))
- - optflag = FALSE;
- - if (!strncmp(rcbuf, "options ", 8))
- - optflag = TRUE;
- - if (optflag) {
- - strcat(rcbuf, "\1");
- - if (space)
- - ptr = rcbuf - 1;
- - else
- - ptr = &rcbuf[7];
- - while (*++ptr)
- - if (isspace(*ptr))
- - *ptr = '\0';
- - if (space)
- - ptr = rcbuf;
- - else
- - ptr = &rcbuf[8];
- - for (;; ptr++) {
- - if (!*ptr)
- - continue;
- - if (*ptr == '\1')
- - break;
- - if (++line > LINES)
- - xerror("Too many options.");
- - if ((rcline[line] = malloc(strlen(ptr) + 1)) == NULL)
- - xerror("Not enough memory.");
- - argvrc[line] = rcline[line];
- - strcpy(rcline[line], ptr);
- - while (*ptr)
- - ptr++;
- - }
- - }
- - }
- - fclose(rcfp);
- - }
- - header.nbuf[0] = 0;
- - if (line != -1) {
- -#ifdef DEBUG
- - for (i = 0; i <= line; i++)
- - fprintf(stderr, "options: %s\n", rcline[i]);
- -#endif
- - process(line+2, argvrc);
- - do {
- -#ifdef DEBUG
- - fprintf(stderr, "Freeing %d\n", line);
- -#endif
- - free(rcline[line]);
- - } while (line--);
- - }
- -
- - if (!*header.nbuf) {
- - strcpy(header.nbuf, DFLTSUB);
- - ngcat(header.nbuf);
- - }
- - strcat(header.nbuf, ADMSUB);
- - ngcat(header.nbuf);
- - if (*header.nbuf)
- - lcase(header.nbuf);
- - makehimask(header.nbuf, "junk");
- - makehimask(header.nbuf, "control");
- - makehimask(header.nbuf, "test");
- - if (access(newsrc, 0)) {
- - if (verbose > 1)
- - printf("No newsrc\n");
- - yep(argv);
- - }
- - if ((rcfp = fopen(newsrc, "r")) == NULL)
- - xerror("Cannot open .newsrc file");
- - while (fgets(rcbuf, LBUFLEN, rcfp) != NULL) {
- - if (!nstrip(rcbuf))
- - xerror(".newsrc line too long");
- - if (++line >= LINES)
- - xerror("Too many .newsrc lines");
- - if ((rcline[line] = malloc(strlen(rcbuf)+1)) == NULL)
- - xerror("Not enough memory");
- - strcpy(rcline[line], rcbuf);
- - }
- - if ((actfp = fopen(ACTIVE, "r")) == NULL)
- - xerror("Cannot open active newsgroups file");
- -
- -#ifdef DEBUG
- - fprintf(stderr, "header.nbuf = %s\n", header.nbuf);
- -#endif
- - nchk(argv);
- - exit(0);
- -}
- -
- -nchk(argv)
- -char **argv;
- -{
- - register int i;
- - register char *ptr;
- - long l;
- - long narts;
- - char saveptr;
- - int isnews = 0;
- - char aline[BUFLEN];
- -
- -#ifdef DEBUG
- - fprintf(stderr, "nchk()\n");
- -#endif
- - while (fgets(aline, sizeof aline, actfp) != NULL) {
- - sscanf(aline, "%s %ld", bfr, &narts);
- -#ifdef DEBUG
- - fprintf(stderr, "bfr = '%s'\n", bfr);
- -#endif
- - ngcat(bfr);
- - if (!ngmatch(bfr, nflag ? narggrp : header.nbuf))
- - continue;
- - ngdel(bfr);
- - i = findrcline(bfr);
- - if (i < 0) {
- - if (verbose>1)
- - printf("No newsrc line for newsgroup %s\n", bfr);
- - strcpy(rcbuf, " 0");
- - } else
- - strcpy(rcbuf, rcline[i]);
- - ptr = rcbuf;
- -
- - if (index(rcbuf, '!') != NULL)
- - continue;
- - if (index(rcbuf, ',') != NULL) {
- - if (verbose > 1)
- - printf("Comma in %s newsrc line\n", bfr);
- - else {
- - isnews++;
- - continue;
- - }
- - }
- - while (*ptr)
- - ptr++;
- - while (!isdigit(*--ptr) && *ptr != ':' && ptr >= rcbuf)
- - ;
- - if (*ptr == ':')
- - continue;
- - if (ptr < rcbuf) {
- - if (verbose > 1)
- - printf("Ran off beginning of %s newsrc line.\n", bfr);
- - yep(argv);
- - }
- - while (isdigit(*--ptr))
- - ;
- - sscanf(++ptr, "%ld", &l);
- - if (narts > l) {
- - if (verbose) {
- - printf("News: %s ...\n", bfr);
- - if (verbose < 2)
- - y = 0;
- - }
- - yep(argv);
- - }
- -contin:;
- - }
- - if (isnews)
- - yep(argv);
- - if (n)
- - printf("No news is good news.\n");
- -}
- -
- -yep(argv)
- -char **argv;
- -{
- - if (y) {
- - if (verbose)
- - printf("There is probably news");
- - else
- - printf("There is news");
- - if (nflag) {
- - narggrp[strlen(narggrp)-1] = '.';
- - printf(" in %s\n",narggrp);
- - }
- - else
- - printf(".\n");
- - }
- - if (e) {
- -#ifdef V6
- - execv("/usr/bin/readnews", argv);
- -#else
- - execvp("readnews", argv);
- -#endif
- - perror("Cannot exec readnews.");
- - }
- - if (q)
- - exit(1);
- - else
- - exit(0);
- -}
- -
- -xerror(message, arg1, arg2)
- -char *message;
- -int arg1, arg2;
- -{
- - char buffer[128];
- -
- - sprintf(buffer, message, arg1, arg2);
- - fprintf(stderr, "checknews: %s.\n", buffer);
- - exit(1);
- -}
- -
- -/*
- - * Append NGDELIM to string.
- - */
- -ngcat(s)
- -register char *s;
- -{
- - if (*s) {
- - while (*s++);
- - s -= 2;
- - if (*s++ == NGDELIM)
- - return;
- - }
- - *s++ = NGDELIM;
- - *s = '\0';
- -}
- -
- -/*
- - * News group matching.
- - *
- - * nglist is a list of newsgroups.
- - * sublist is a list of subscriptions.
- - * sublist may have "meta newsgroups" in it.
- - * All fields are NGDELIM separated,
- - * and there is an NGDELIM at the end of each argument.
- - *
- - * Currently implemented glitches:
- - * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
- - * If subscription X matches Y, it also matches Y.anything.
- - */
- -ngmatch(nglist, sublist)
- -register char *nglist, *sublist;
- -{
- - register char *n, *s;
- - register int rc;
- -
- - rc = FALSE;
- - for (n = nglist; *n != '\0' && rc == FALSE;) {
- - for (s = sublist; *s != '\0';) {
- - if (*s != NEGCHAR)
- - rc |= ptrncmp(s, n);
- - else
- - rc &= ~ptrncmp(s+1, n);
- - while (*s++ != NGDELIM);
- - }
- - while (*n++ != NGDELIM);
- - }
- - return(rc);
- -}
- -
- -/*
- - * Compare two newsgroups for equality.
- - * The first one may be a "meta" newsgroup.
- - */
- -ptrncmp(ng1, ng2)
- -register char *ng1, *ng2;
- -{
- - while (*ng1 != NGDELIM) {
- - if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
- - ng1 += 3;
- - while (*ng2 != NGDELIM && *ng2 != '.')
- - if (ptrncmp(ng1, ng2++))
- - return(TRUE);
- - return (ptrncmp(ng1, ng2));
- - } else if (*ng1++ != *ng2++)
- - return(FALSE);
- - }
- - return (*ng2 == '.' || *ng2 == NGDELIM);
- -}
- -
- -/*
- - * Get user name and home directory.
- - */
- -getuser()
- -{
- - static int flag = TRUE;
- - register struct passwd *p;
- -
- - if (flag) {
- - if ((p = getpwuid(getuid())) == NULL)
- - xerror("Cannot get user's name");
- - if (username == NULL || *username == '\0')
- - username = AllocCpy(p->pw_name);
- - userhome = AllocCpy(p->pw_dir);
- - flag = FALSE;
- - }
- -}
- -
- -/*
- - * Strip trailing newlines, blanks, and tabs from 's'.
- - * Return TRUE if newline was found, else FALSE.
- - */
- -nstrip(s)
- -register char *s;
- -{
- - register char *p;
- - register int rc;
- -
- - rc = FALSE;
- - p = s;
- - while (*p)
- - if (*p++ == '\n')
- - rc = TRUE;
- - while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
- - *++p = '\0';
- - return(rc);
- -}
- -
- -/*
- - * Delete trailing NGDELIM.
- - */
- -ngdel(s)
- -register char *s;
- -{
- - if (*s++) {
- - while (*s++);
- - s -= 2;
- - if (*s == NGDELIM)
- - *s = '\0';
- - }
- -}
- -
- -lcase(s)
- -register char *s;
- -{
- - register char *ptr;
- -
- - for (ptr = s; *ptr; ptr++)
- - if (isupper(*ptr))
- - *ptr = tolower(*ptr);
- -}
- -
- -/*
- - * finds the line in your .newsrc file (actually the in-core "rcline"
- - * copy of it) and returns the index into the array where it was found.
- - * -1 means it didn't find it.
- - *
- - * We play clever games here to make this faster. It's inherently
- - * quadratic - we spend lots of CPU time here because we search through
- - * the whole .newsrc for each line. The "prev" variable remembers where
- - * the last match was found; we start the search there and loop around
- - * to the beginning, in the hopes that the calls will be roughly in order.
- - */
- -int
- -findrcline(name)
- -char *name;
- -{
- - register char *p, *ptr;
- - register int cur;
- - register int i;
- - register int top;
- - static int prev = 0;
- -
- - top = line; i = prev;
- -loop:
- - for (; i <= top; i++) {
- - for (p = name, ptr = rcline[i]; (cur = *p++); ) {
- - if (cur != *ptr++)
- - goto contin2;
- - }
- - if (*ptr != ':' && *ptr != '!')
- - continue;
- - prev = i;
- - return i;
- -contin2:
- - ;
- - }
- - if (i > line && line > prev-1) {
- - i = 0;
- - top = prev-1;
- - goto loop;
- - }
- - return -1;
- -}
- -
- -/*
- - * Forbid newsgroup ng, unless he asked for it in nbuf.
- - */
- -makehimask(nbuf, ng)
- -char *nbuf, *ng;
- -{
- - if (!findex(nbuf, ng)) {
- - ngcat(nbuf);
- - strcat(nbuf, "!");
- - strcat(nbuf, ng);
- - ngcat(nbuf);
- - }
- -}
- -
- -/*
- - * Return true if the string searchfor is in string, but not if preceded by !.
- - */
- -findex(string, searchfor)
- -char *string, *searchfor;
- -{
- - register char first;
- - register char *p;
- -
- - first = *searchfor;
- - for (p=index(string, first); p; p = index(p+1, first)) {
- - if (p>string && p[-1] != '!' && strncmp(p, searchfor, strlen(searchfor)) == 0)
- - return TRUE;
- - }
- - return FALSE;
- -}
- -
- -xxit(i)
- -{
- - exit(i);
- -}
- *-*-END-of-src/checknews.c-*-*
- echo x - src/recnews.c 1>&2
- sed 's/.//' >src/recnews.c <<'*-*-END-of-src/recnews.c-*-*'
- -/*
- - * recnews [to newsgroup] [from user]
- - *
- - * Process a news article which has been mailed to some group like msgs.
- - * Such articles are in normal mail format and have never seen the insides
- - * of netnews. If the "to newsgroup" is included, the article is posted
- - * to this newsgroup instead of trying to intuit it from the headers.
- - * If the "from user" is included, the return address is forged to look
- - * like that user instead of what getuid or a from line says.
- - *
- - * It is recommended that you always include the to newsgroup, since the
- - * intuition code is flakey and out of date. The from user is probably
- - * appropriate for arpanet mailing lists being funnelled at ucbvax but
- - * not otherwise. Sample lines in /usr/lib/aliases (if you run delivermail):
- - * worldnews: "|/usr/lib/news/recnews net.general"
- - * Allows you to mail to worldnews rather than using inews.
- - * Intended for humans to mail to.
- - * post-unix-wizards: "|/usr/lib/news/recnews fa.unix-wizards unix-wizards"
- - * Causes mail to post-unix-wizards to be fed into fa.unix-wizards
- - * and the return address forged as unix-wizards on the local
- - * machine. post-unix-wizards (on the local machine) should
- - * be part of the master mailing list somewhere (on a different
- - * machine.)
- - *
- - * Recnews is primarily useful in remote places on the usenet which collect
- - * mail from mailing lists and funnel them into the network. It is also
- - * useful if you like to send mail to some user instead of invoking
- - * inews -t .. -n .. when you want to submit an article. (Many mailers give
- - * you nice facilities like editing the message.) It is not, however,
- - * essential to use recnews to be able to join usenet.
- - *
- - * WARNING: recnews disables the "recording" check - it has to because
- - * by the time inews is run, it's in the background and too late to
- - * ask permission. If you depend heavily on recordings you probably
- - * should not allow recnews (and thus the mail interface) to be used.
- -*
- - * 1) We leave the from line alone. Just escape the double quotes, but let the
- - * mailer do the rest.
- - * 2) We give precedence to "From:" over "From " or ">From " in determining
- - * who the article is really from.
- - * Modifications by rad@tek
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)recnews.c 2.13 10/23/86";
- -#endif /* SCCSID */
- -
- -#include "defs.h"
- -
- -#include <stdio.h>
- -#include <ctype.h>
- -
- -/*
- - * Note: we assume there are 2 kinds of hosts using recnews:
- - * Those that have delivermail (and hence this program will never
- - * have to deal with more than one message at a time) and those on the arpanet
- - * that do not (and hence all messages end with a sentinel). It is
- - * supposed that regular v7 type systems without delivermail or some
- - * other automatic forwarding device will just use rnews. We do
- - * not attempt to tell where a message ends on all systems due to the
- - * different conventions in effect. (This COULD be fixed, I suppose.)
- - */
- -
- -/*
- - * Kinds of lines in a message.
- - */
- -#define FROM 001 /* From line */
- -#define SUBJ 002 /* Subject */
- -#define TO 003 /* To (newgroup based on this) */
- -#define BLANK 004 /* blank line */
- -#define EOM 005 /* End of message (4 ctrl A's) */
- -#define HEADER 006 /* any unrecognized header */
- -#define TEXT 007 /* anything unrecognized */
- -#define INCLUSIVE 010 /* newsgroup is already in header */
- -
- -/*
- - * Possible states program can be in.
- - */
- -#define SKIPPING 0100 /* In header of message */
- -#define READING 0200 /* In body of message */
- -
- -#define BFSZ 250
- -
- -#define EOT '\004'
- -
- -char from[BFSZ]; /* mailing address for replies */
- -char sender[BFSZ]; /* mailing address of author, if different */
- -char to[BFSZ]; /* Destination of mail (msgs, etc) */
- -char subject[BFSZ]; /* subject of message */
- -char newsgroup[BFSZ]; /* newsgroups of message */
- -int fromset; /* from passed on command line */
- -char cmdbuf[BFSZ]; /* command to popen */
- -
- -extern char *strcat(), *strcpy();
- -extern FILE *popen();
- -char *any();
- -
- -main(argc, argv)
- -int argc;
- -char **argv;
- -{
- - char buf[BFSZ], inews[BFSZ];
- - register char *p, *q;
- - register FILE *pipe = NULL;
- - register int state;
- -
- - /* build inews command */
- -#ifdef IHCC
- - sprintf(inews, "%s/%s/%s", logdir(HOME), LIBDIR, "inews");
- -#else
- - sprintf(inews, "%s/%s", LIBDIR, "inews");
- -#endif
- -
- - if (argc > 1)
- - strcpy(to, argv[1]);
- - if (argc > 2)
- - strcpy(from, argv[2]);
- -
- - /*
- - * Flag that we know who message is from to avoid trying to
- - * decipher the From line.
- - */
- - if (argc > 2 && (argv[2][0] != '\0'))
- - fromset++;
- -
- -#ifdef debug
- - printf("argv[0] is <%s>, argv[1] is <%s>, argv[2] is <%s>\n",
- - argv[0], argv[1], argv[2]);
- -#endif
- - state = SKIPPING;
- - while (fgets(buf, BFSZ, stdin) != NULL) {
- - if (state == READING) {
- - fputs(buf,pipe);
- - continue;
- - }
- - switch (type(buf)) {
- -
- - case FROM:
- - frombreak(buf, from);
- - break;
- -
- - case SUBJ:
- - p = any(buf, " \t");
- - if (p == NULL)
- - p = buf + 8;
- - q = subject;
- - while (*++p) {
- - if (*p == '"')
- - *q++ = '\\';
- - *q++ = *p;
- - }
- - q[-1] = '\0';
- - break;
- -
- - case TO:
- - if (to[0])
- - break; /* already have one */
- - p = any(buf, " \t");
- - if (p == NULL)
- - p = buf + 3;
- - q = to;
- - while (*++p) {
- - if (*p == '"')
- - *q++ = '\\';
- - *q++ = *p;
- - }
- - q[-1] = '\0';
- - break;
- -
- - case INCLUSIVE:
- - sprintf(cmdbuf,"exec %s -p", inews);
- - pipe = popen(cmdbuf,"w");
- - if (pipe == NULL){
- - perror("recnews: open failed");
- - exit(1);
- - }
- - state = READING;
- - fputs(buf,pipe);
- - break;
- -
- - /*
- - * Kludge to compensate for messages without real headers
- - */
- - case HEADER:
- - break;
- -
- - case BLANK:
- - state = READING;
- - strcpy(newsgroup, to);
- - sprintf(cmdbuf, "exec %s -t \"%s\" -n \"%s\" -f \"%s\"",
- - inews, *subject ? subject : "(none)",
- - newsgroup, from);
- -#ifdef debug
- - pipe = stdout;
- - printf("BLANK: %s\n", cmdbuf);
- -#else
- - pipe = popen(cmdbuf, "w");
- - if (pipe == NULL) {
- - perror("recnews: popen failed");
- - exit(1);
- - }
- -#endif
- - if (sender[0]) {
- - fputs(sender, pipe);
- - putc('\n', pipe);
- - }
- - break;
- -
- - case TEXT:
- - strcpy(newsgroup, to);
- - state = READING;
- - if (subject[0] == 0) {
- - strcpy(subject, buf);
- - if (subject[strlen(subject)-1] == '\n')
- - subject[strlen(subject)-1] = '\0';
- - }
- - sprintf(cmdbuf, "exec \"%s\" -t \"%s\" -n \"%s\" -f \"%s\"",
- - inews, subject, newsgroup, from);
- -#ifdef debug
- - pipe = stdout;
- - printf("TEXT: %s\n", cmdbuf);
- -#else
- - pipe = popen(cmdbuf, "w");
- - if (pipe == NULL) {
- - perror("pipe failed");
- - exit(1);
- - }
- -#endif
- - if (sender[0]){
- - fputs(sender, pipe);
- - putc('\n',pipe);
- - }
- - break;
- - }
- - }
- - exit(0);
- -}
- -
- -type(p)
- -register char *p;
- -{
- - char *firstbl;
- - static char lasthdr = 1; /* prev line was a header */
- -
- - if ((*p == ' ' || *p == '\t') && lasthdr)
- - return HEADER; /* continuation line */
- - firstbl = any(p, " \t");
- - while (*p == ' ' || *p == '?' || *p == '\t')
- - ++p;
- -
- - if (*p == '\n' || *p == 0)
- - return BLANK;
- - if (strncmp(p, ">From", 5) == 0 || strncmp(p, "From", 4) == 0)
- - return FROM;
- - if (strncmp(p, "Subj", 4)==0 || strncmp(p, "Re:", 3)==0 ||
- - strncmp(p, "re:", 3)==0)
- - return SUBJ;
- - if (strncmp(p, "To", 2)==0)
- - return TO;
- - if (strncmp(p, "\1\1\1\1", 4)==0)
- - return EOM;
- - if (firstbl && firstbl[-1] == ':' && isalpha(*p))
- - return HEADER;
- - lasthdr = 0;
- - return TEXT;
- -}
- -
- -/*
- - * Figure out who a message is from.
- - */
- -frombreak(buf, fbuf)
- -register char *buf, *fbuf;
- -{
- - register char *p, *q;
- -
- - if (fbuf[0] && fromset) { /* we already know who it's from */
- - if (sender[0] == 0 || buf[4] == ':') {
- -#ifdef debug
- - printf("sender set to: %s", buf);
- -#endif
- - strcpy(sender, buf);
- - }
- - return;
- - }
- - /*
- - * Leave fancy Froms alone - this parsing is done by mail
- - * Just quote the double quotes to prevent interpetation
- - * by the shell.
- - * rad@tek
- - */
- - p = any(buf, " \t");
- - if (p==NULL)
- - p = buf + 4;
- - q = fbuf;
- - while (*++p) {
- - if (*p == '"')
- - *q++ = '\\';
- - *q++ = *p;
- - }
- - q[-1] = '\0';
- - if ((p=(char *)index(fbuf,'\n')) != NULL)
- - *p = '\0';
- - if (buf[4] == ':')
- - fromset++;
- -}
- -
- -/*
- - * Return the ptr in sp at which a character in sq appears;
- - * NULL if not found
- - *
- - */
- -char *
- -any(sp, sq)
- -char *sp, *sq;
- -{
- - register c1, c2;
- - register char *q;
- -
- - while (c1 = *sp++) {
- - q = sq;
- - while (c2 = *q++)
- - if (c1 == c2)
- - return(--sp);
- - }
- - return(NULL);
- -}
- *-*-END-of-src/recnews.c-*-*
- echo x - src/rextern.c 1>&2
- sed 's/.//' >src/rextern.c <<'*-*-END-of-src/rextern.c-*-*'
- -/*
- - * rextern - external definitions for readnews
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)rextern.c 2.15 4/16/85";
- -#endif /* SCCSID */
- -
- -/*LINTLIBRARY*/
- -
- -#include "rparams.h"
- -
- -int uid, gid; /* real user/group I.D. */
- -int duid, dgid; /* effective user/group I.D. */
- -int SigTrap; /* set if signal trapped */
- -int savmask; /* old umask */
- -int mode; /* mode of news program */
- -struct hbuf header; /* general-use header structure */
- -char bfr[LBUFLEN]; /* general-use scratch area */
- -
- -#ifndef ROOTID
- -int ROOTID; /* special users id # */
- -#endif
- -
- -char *outfile = "/tmp/M1XXXXXX"; /* output file for -M and -c */
- -char *infile = "/tmp/M2XXXXXX"; /* -T output from Mail */
- -int ngrp, line = -1;
- -
- -char filename[BUFLEN], coptbuf[BUFLEN], datebuf[BUFLEN];
- -char afline[BUFLEN];
- -FILE *rcfp, *actfp;
- -time_t atime;
- -char newsrc[BUFLEN], groupdir[BUFLEN], *rcline[LINES], rcbuf[LBUFLEN];
- -char *bitmap, *argvrc[LINES];
- -long bit, obit, last;
- -int readmode = NEXT;
- -int news = 0; /* Was there any news to read */
- -int actdirect = FORWARD; /* read direction in ACTIVE file */
- -int rcreadok = FALSE; /* NEWSRC has been read OK */
- -int zapng = FALSE; /* ! out this newsgroup on next updaterc */
- -long ngsize; /* max article # in this newsgroup */
- -long minartno; /* min article # in this newsgroup */
- -
- -#ifndef SHELL
- -char *SHELL;
- -#endif
- -
- -#ifndef MAILER
- -char *MAILER;
- -#endif
- -
- -char *PAGER = "";
- *-*-END-of-src/rextern.c-*-*
- exit
-
-